function [xmlStruct, xml,status,dasUrl, xmlStruct2] = executeDASCommand(serverURL,varargin)
% EXECUTEDASCOMMAND is the DAS Version 1.53 API.
%
% EXECUTEDASCOMMAND executes a DAS query to the specified DAS service. For a full description of
% the commands, including formats of DAS commands in this
% version check out http://www.biodas.org/documents/spec.html.
% 
% EXECUTEDASCOMMAND has a very flexible input format to embrace the whole
% set of DAS commands and their arguments. See EXAMPLES below to get to know how to
% call an specific DAS cabapiblity and pass the needed arguments for
% running it. Each capability has its own set of arguments.
%
%EXAMPLES: 
%
% DSN, ENTRY_POINTS, STYLESHEET queries - just provide the url for the DAS
% service and the command, without arguments. Timeout defines the maximum
% amount of time allowed for the server to return the query, and can be
% specified for all queries (in miliseconds).
% 
    % eg. Finding out data sources available in a DAS server
    % [xmlS, xml] =
    % executeDasCommand('http://www.ebi.ac.uk/das-srv/uniprot/das', ...
    %'command','dsn','timeout', 15000)
%     
    % eg. Finding out entry_points in the specified DAS service
    % [xmlS, xml]=
    % executeDasCommand('http://www.ebi.ac.uk/das-srv/uniprot/das','command', ...
    % 'entry_points', 'DSN', 'uniprot-goa')
%     
% 
% DNA, SEQUENCE, TYPES, FEATURES, STRUCTURE, INTERACTION and ALIGNMENT queries - provide the url for DAS service,
% command, and segment definitions. Segment can be eiher a fragment in the
% referenced sequence or an ID that identifies the segment.
% 
    % eg. Retrieving DNA sequence
    %[xmlS, xml] = executeDASCommand('http://genome.cse.ucsc.edu/cgi-bin/das','command', 'dna', 'DSN', 'hg16','chrom','6','start','37429768' ...
    %, 'stop', '37470491')
% 
    % eg. Retrieving AA sequence with SEQUENCE command
    %[xmlS, xml] =
    %executeDASCommand('http://www.ebi.ac.uk/das-srv/uniprot/das','command', ...
    %'sequence', 'DSN', 'uniprot','segment','A4_HUMAN')
% 
    % eg. Get the features annotated for the sequence with TYPES command
    %[xmlS, xml] =
    %executeDASCommand('http://www.ebi.ac.uk/das-srv/uniprot/das','command', ...
    %'types', 'DSN', 'uniprot','segment','A4_HUMAN')
%     
    % eg. Get the 3D structure of a protein using STRUCTURE command
    %[xmlS, xml] =
    %executeDASCommand('http://das.sanger.ac.uk/das','command', ...
    %'structure', 'DSN', 'structure','segment','1a4a')
%     
    % eg. Retrieve pairwise/multiple alignment with ALIGNMENT command
    %[xmlS, xml] =
    %executeDASCommand('http://das.sanger.ac.uk/das','command', ...
    %'alignment', 'DSN', 'msdpdbsp','segment','P50225')
%     
    % eg. Retrieve ptn-ptn interactions with INTERACTION command
    %[xmlS, xml] =
    %executeDASCommand('http://dasmi.bioinf.mpi-inf.mpg.de/das','command', ...
    %'interaction', 'DSN', 'sanger','segment','10526')
%     
%     
% 
% FEATURES query - provide the url for DAS service,
% command, segment definitions and the list of features (optional). Segment can be eiher a fragment in the
% referenced sequence or an ID that identifies the segment.
% 
    % Get all features description for the A4_HUMAN protein
    % [xmlS, xml] =
    % executeDASCommand('http://www.ebi.ac.uk/das-srv/uniprot/das','command', ...
    % 'features', 'DSN', 'uniprot','segment','A4_HUMAN')
% 
% SPECIFY the full url for the query
% [xmlS, xml, status] = executeDASCommand('empty','queryURL',url)
%
% See also SEARCHDASREGISTRY
% 
%   DASMiner: DAS library and browser for Matlab.
%   Diogo Veiga, March 2008.

p = inputParser;   % Create an instance of the class.

p.addRequired('serverURL', @ischar); %check if it is in the registry
p.addParamValue('command', '', @(x) isValidCommand(x) );
p.addParamValue('queryURL', '', @ischar); %write fction to check if its a valid url
p.addParamValue('DSN', '', @ischar);
p.addParamValue('segment', '', @ischar); %check if it is a valid ID?
p.addParamValue('chrom', '', ...
     @(x) isinteger(x) || isStrNumber(x));
p.addParamValue('start', '', ...
     @(x) isinteger(x) || isStrNumber(x) ); %check if string corresponds to a double
p.addParamValue('stop', '');
p.addParamValue('featuresList', '', @iscellstr);
p.addParamValue('timeout', 30000, @isnumeric); %time in miliseconds
p.addParamValue('debug',1, @(x) isinteger(x));

p.KeepUnmatched = true;
p.FunctionName = 'EXECUTEDASCOMMAND';
p.parse(serverURL, varargin{:});


if (strcmp(p.Results.command,'') && strcmp(p.Results.queryURL,''))
    error('No command or query URL defined.');
end

if (strcmp(serverURL(end),'/'))
    serverURL = serverURL(1:end-1);
end

if (strcmp(p.Results.command,'dsn'))
    dasUrl = strcat(serverURL, '/', p.Results.command); 
end

if (isempty(p.Results.command))
    dasUrl = p.Results.queryURL; 
end

if (any(strcmpi(p.Results.command,{'entry_points','stylesheet'})) ) %Requires DSN
    if (strcmp(p.Results.DSN,''))
        error('Query entry_points? needs parameter DSN');
    end
    dasUrl = strcat(serverURL, '/', p.Results.DSN, '/', p.Results.command); 
end

if (any(strcmpi(p.Results.command,{'dna','sequence','types','features','structure','alignment','interaction'})) ) %Requires DSN and Segment definitions

    if (strcmp(p.Results.DSN,''))
        error('Query sequence? needs parameter DSN');
    end
     
    if (~strcmp(p.Results.segment,''))

        if (any(strcmpi(p.Results.command,{'structure','alignment'})))
            dasUrl = strcat(serverURL, '/', p.Results.DSN, '/', p.Results.command, '?query=', p.Results.segment);
        elseif (strcmp(p.Results.command,'interaction')) 
            dasUrl = strcat(serverURL, '/', p.Results.DSN, '/', p.Results.command, '?interactor=', p.Results.segment);
        else
            dasUrl = strcat(serverURL, '/', p.Results.DSN, '/', p.Results.command, '?segment=', p.Results.segment);
        end

    else
        if (any(strcmpi(p.Results.command,{'structure','alignment','interaction'})))
            error('Query %s? needs parameter segment.',p.Results.command);
        end
                
        if ( strcmp(p.Results.chrom,'') || strcmp(p.Results.start,'') || strcmp(p.Results,'')  )
            error('Query dna? needs parameters chrom, start, stop.');
        else
            dasUrl = strcat(serverURL, '/', p.Results.DSN, '/', p.Results.command, '?segment=', p.Results.chrom, ...
                ':', p.Results.start, ',', p.Results.stop);
        end
    end

    if ((~isempty(p.Results.featuresList)) && (strcmp(p.Results.command,'features')) )

        for i=1:size(p.Results.featuresList,2)
            dasUrl = strcat(dasUrl,';type=',p.Results.featuresList{1,i});
        end
        dasUrl = strcat(dasUrl,';categoryze=yes');
    end
     
end

if (p.Results.debug)
    disp(['Retrieving ......... ' dasUrl ]);
end

tic
[xmlStruct, xml, status, xmlStruct2] = readDASURL(dasUrl,p.Results.timeout);

t = toc;
if (p.Results.debug)
    if (status == 0)
        smsg = 'Failed - Bad url or server is not responding';
    elseif (~isstruct(xmlStruct) )
        smsg = 'Failed - Problem parsing XML';
    else
        smsg = 'Okay';
    end
    disp(['Done .........  Status: ' smsg ' Time elapsed: ' num2str(t) 's' ]);
end
    
   
% ARGUMENT VALIDATION FUNCTIONS
function [res] = isStrNumber(x)

[t,res] = str2num(x);

function [res] = isValidCommand(x)

res = any(strcmpi(x,{'dsn','entry_points', 'dna', 'sequence', 'types', 'features', 'stylesheet', 'structure', 'alignment','interaction'}));


